import sys
import pyaudio
import io
import os
import threading
import serial
import time
import logging
sys.path.append("/home/elf/project_code2")
sys.path.append("/home/elf/project_code2/Vission")
sys.path.append("/home/elf/project_code2/Vission/codes")
sys.path.append("/home/elf/project_code2/Hardware")
from Vission.codes import *
from aip import AipSpeech
from pydub import AudioSegment
from Navigation.GPS import navigation
from Hardware.servo import *
from Application.utils import tts_speak
from Application.application import mission
from Vission.codes.message_queue import *




logging.basicConfig(
        level=logging.INFO,
        format="%(asctime)s [%(levelname)s] %(message)s",
        handlers=[logging.FileHandler("/home/elf/project_code2/app.log"), logging.StreamHandler()]
    )

SERIAL_PORT = "/dev/ttyS9"
BAUD_RATE = 9600
# 百度语音合成 API 配置
APP_ID = ...
API_KEY = ...
SECRET_KEY = ...
client = AipSpeech(APP_ID, API_KEY, SECRET_KEY)

# 地名映射
LOCATION_MAP = {
    "tsg": "华中科技大学图书馆",
    "xyy": "华中科技大学校医院",
    "djl": "华中科技大学东九楼",
    "ndm": "华中科技大学南大门"
}



class VoiceAssistant:
    def __init__(self):
        self.state = "IDLE"
        self.city = "湖北省武汉市"
        self.mission=None

    def start_navigation(self, targetname,speaker)->mission:
        try:
            self.mission=mission(speaker,self.city, targetname,mode="navigation")
            #logging.info(f"导航到 {targetname} 开始")
        except Exception as e:
            logging.error(f"导航模块失败: {e}")
            tts_speak("导航失败，请重试")
    
    def start_walking(self,speaker)->mission:
        try:
            self.mission=mission(speaker,mode="walking")
            logging.info("开启散步模式")
            message="开启散步模式"
            self.mission.message_queue.push(speech_message(priority=Priority.Text, subpriority=Subpriority.A, message=message))

        except Exception as e:
            logging.error(f"散步模式开启失败，{e}")

            
    def process_command(self, command,speaker):
        logging.debug(f"处理指令: '{command}'")

        if command == "WAKE":
            self.state = "IDLE"
            tts_speak("在呢")
        elif self.state == "IDLE":
            self.state = "IDLE"
            if command in LOCATION_MAP:    #导航模式>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                self.start_navigation(LOCATION_MAP[command],speaker)
            elif command =="sbm":          #散步模式>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                self.start_walking(speaker)
            elif command =="tz":
                if self.mission is not None:
                    self.mission.stop()
                



def listen_task(speaker,assistant:VoiceAssistant):
    try:
        ser = serial.Serial(SERIAL_PORT, BAUD_RATE, bytesize=8, parity='N', stopbits=1, timeout=1)
        logging.info(f"[broadcast] 成功打开串口 {SERIAL_PORT}，波特率 {BAUD_RATE}")
    except Exception as e:
        logging.error(f"无法打开串口 {SERIAL_PORT}: {e}")
        exit(1)
    try:
        while True:
            try:
                if ser.in_waiting > 0:
                    raw_data = ser.readline()
                    logging.debug(f"原始字节: {raw_data.hex()}")
                    command = raw_data.decode('utf-8', errors='replace').strip()
                    if command:
                        assistant.process_command(command,speaker)
                    else:
                        logging.debug("收到空指令")
                else:
                    logging.debug("无串口数据")
            except Exception as e:
                logging.error(f"串口读取错误: {e}")
            time.sleep(0.5)
    except KeyboardInterrupt:
        logging.info("程序终止")
    finally:
        ser.close()
        logging.info("串口已关闭")
        cleanup_pwm()

def main():
    speaker = VoiceAssistant()
    assistant = VoiceAssistant()
    
    # 创建一个事件对象用于控制程序运行
    running_event = threading.Event()
    running_event.set()  # 设置为True
    
    listen_thread = threading.Thread(target=listen_task, args=(speaker, assistant), daemon=True)
    listen_thread.start()
    
    try:
        # 主线程低占用循环
        while running_event.is_set():
            time.sleep(10) # 短暂休眠，减少CPU占用
            #running_event.clear()
    except KeyboardInterrupt:
        running_event.clear()  # 清除事件，准备退出
        logging.info("收到终止信号，准备退出...")
    finally:
        cleanup_pwm()

if __name__ == "__main__":
    main()

